#include <stdio.h>
#include <string.h>
#include <GL/glut.h>

#include <stack>
#define WINDOW_HEIGHT 400
#define MAXN 100

using namespace std;

struct dcpt {
	int x, y;
};

typedef dcpt Direction;

Direction dir[] = {
	{0, -1}, /* 上 */
	{1,  0}, /* 左 */
	{0,  1}, /* 下 */
	{-1, 0} /* 右 */
};

// bool visited[MAXN][MAXN];

unsigned char *fillColor, *borderColor;

bool SameColor(unsigned char * p1, unsigned char *p2) {
	for(int i=0; i<4; i++) {
		if(p1[i] != p2[i])
			return false;
	}

	return true;
}

void Boundaryfill(int seedx, int seedy) {
	stack<dcpt> stk1;
	/*long color = RGB(255, 0, 0); // Filled Color
	long boundary_color = RGB(255, 255, 255); // Boundary Color
	unsigned char params[4];*/
	unsigned char *params = (unsigned char *)malloc(sizeof(char)*4);

	dcpt p1;
	p1.x = seedx;
	p1.y = seedy;

	// 重置访问数组
	/*for(int i=0; i<MAXN; i++) {
		for(int j=0; j<MAXN; j++)
			visited[i][j] = false;
	}*/

	// Begin to Fill
	stk1.push(p1);
	//visited[p1.y][p1.x] = true;
	/*glReadPixels(seedx+1, seedy+1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, params);
	unsigned char * interiorColor = params;
	for(int i=0; i<4; i++)
		printf("Interior: %d ", params[i]);
	printf("\n");

	glReadPixels(seedx, seedy+1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, params);
	for(int i=0; i<4; i++)
		printf("Interior: %d ", params[i]);
	printf("\n");*/


	while(!stk1.empty()) {
		dcpt temp = stk1.top();
		stk1.pop();

		// 四个方向
		for(int k=0; k<3; k++) {	
			dcpt now = temp;
			now.x += dir[k].x;
			now.y += dir[k].y;

			glReadPixels(now.x, now.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, params);
			unsigned char * interiorColor = params;

			for(int i=0; i<4; i++)
				printf("Interior: %d ", interiorColor[i]);
			printf("\n");
			printf("SameColor: %d\n", SameColor(interiorColor, borderColor));
			printf("SameColor: %d\n", SameColor(interiorColor, fillColor));

			/*if(!SameColor(interiorColor, borderColor) && !SameColor(interiorColor, fillColor)) {
				glColor3f(1.0, 0.0, 0.0);
				glBegin(GL_POINTS);
					glVertex2i(now.x, now.y);
				glEnd();
				stk1.push(now);
			}*/
		}
	}
}

void MyPolygonFill(int n, dcpt * vertices) {	
	int max = vertices[0].x;
	int mix = vertices[0].x;
	int may = vertices[0].y;
	int miy = vertices[0].y;

	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_LOOP);
		for(int i=0; i<n; i++) {
			glVertex2i(vertices[i].x, vertices[i].y);
			if(vertices[i].x > max)
				max = vertices[i].x;
			if(vertices[i].x < mix)
				mix = vertices[i].x;
			if(vertices[i].y > may)
				may = vertices[i].y;
			if(vertices[i].y < miy)
				miy = vertices[i].y;
		}
	glEnd();

	unsigned char *params = (unsigned char *)malloc(sizeof(char)*4);
	int x = vertices[0].x;
	int y = vertices[0].y;
	glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, params);
	borderColor = params;
	for(int i=0; i<4; i++)
		printf("Border: %d ", params[i]);
	printf("\n");

	int sx = (max+mix)/2;
	int sy = (may+miy)/2;
	/*	glReadPixels(sx, sy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, params);
	for(int i=0; i<4; i++)
		printf("Inter: %d ", params[i]);
	printf("\n"); */

	glColor3f(1.0, 0.0, 0.0);
	glBegin(GL_POINTS);
		glVertex2i(sx, sy);
		fillColor = (unsigned char *)malloc(sizeof(char)*4);
		glReadPixels(sx, sy, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, fillColor);
		for(int i=0; i<4; i++)
			printf("Fill Color: %d ", fillColor[i]);
		printf("\n");
	glEnd();

	//Boundaryfill(sx, sy);
}

void Init(void) {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glPixelStorei(GL_PACK_ALIGNMENT, 1);
}

void display(void) {
	static dcpt v[4];
	v[0].x = 260, v[0].y = 150;
	v[1].x = 281, v[1].y = 200;
	v[2].x = 340, v[2].y = 230;
	v[3].x = 370, v[3].y = 150;

	glClear(GL_COLOR_BUFFER_BIT);

	MyPolygonFill(4, v);

	glFlush();
}

void reshape(int w, int h) {
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, w, 0, h);
}

void keyboard(unsigned char key, int x, int y) {
	switch(key) {
		case 27: exit(0);
	}
}

int main(int argc, char * argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(50, 100);
	glutInitWindowSize(650, 400);
	glutCreateWindow("Polygon Fill");

	Init();

	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	
	glutMainLoop();
	
	return 0;
}
